﻿#include <QFile>
#include <QTimer>
#include <QDebug>
#include <QDir>
#include <QMessageBox>
#include <QDateTime>
#include "CLogHisDlg.h"
#include "CLogMng.h"
#include "CLogDetails.h"

CLogHisDlg::CLogHisDlg(const QString& moduleName, const QVector<QString>& vecDeviceNames, int nType, QWidget *parent)
	: QDialog(parent)
	, m_sModuleName(moduleName)
	, m_vecDeviceNames(vecDeviceNames)
	, m_nMaxDisplayCount(100)
	, m_nNo(0)
	, m_nType(nType)
	, m_currentPage(1)
	, m_totalPages(1)
	, m_pageSize(500)  // 默认值，会在initUI中从配置读取
{
	ui.setupUi(this);
	setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
	this->setWindowTitle(QString::fromLocal8Bit("历史日志查询"));
	initConnect();
	initUI();
	initModel();
	slotPushQuery();
}

CLogHisDlg::~CLogHisDlg()
{}

void CLogHisDlg::initConnect()
{
	connect(ui.pushButtonQuery, &QPushButton::clicked, this, &CLogHisDlg::slotPushQuery);
	connect(ui.pushButtonPre, &QPushButton::clicked, this, &CLogHisDlg::slotPushPrePage);
	connect(ui.pushButtonNext, &QPushButton::clicked, this, &CLogHisDlg::slotPushNextPage);
	connect(ui.pushButtonPreDay, &QPushButton::clicked, this, &CLogHisDlg::slotPushPreDay);
	connect(ui.pushButtonAddDay, &QPushButton::clicked, this, &CLogHisDlg::slotPushAddDay);
	connect(ui.tableView, &QTableView::doubleClicked, this, &CLogHisDlg::slotDoubleClick);
}

void CLogHisDlg::initUI()
{
	// 从配置获取每页显示条数
	CLogMng& logMng = CLogMng::instance();
	if (logMng.m_isShowLimit)
	{
		m_pageSize = logMng.m_showLimit;
	}
	else
	{
		m_pageSize = 500; // 默认500条
	}

	ui.tabWidget->setTabText(0, m_sModuleName);
	ui.comboBoxLevel->addItem("*");
	ui.comboBoxDevice->addItem("*");
	for (auto itor = CLogMng::instance().m_mapLogLevelConfigs.begin(); itor != CLogMng::instance().m_mapLogLevelConfigs.end(); itor++)
	{
		QPixmap pixmap(itor.value().iconPath);
		ui.comboBoxLevel->addItem(QIcon(pixmap), itor.value().desc);
	}
	if (m_nType == 0)
	{
		for (int i = 0; i < m_vecDeviceNames.size(); i++)
		{
			ui.comboBoxDevice->addItem(m_vecDeviceNames[i]);
		}
	}
	else if (m_nType == 1)
	{
		QString sPath = QCoreApplication::applicationDirPath() + "/Log/" + m_sModuleName;
		QDir dir(sPath);
		if (dir.exists())
		{
			// 设置过滤器：只获取目录，不获取文件
			dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
			// 获取所有目录名称
			QStringList folderNames = dir.entryList();
			ui.comboBoxDevice->addItems(folderNames);
			m_vecDeviceNames = folderNames.toVector();
		}
	}

	// 设置日期为今天
	ui.dateEdit->setDate(QDate::currentDate());

	//表格相关
	ui.tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
	ui.tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
	ui.tableView->setAlternatingRowColors(true);
	ui.tableView->verticalHeader()->setVisible(false);
	ui.tableView->horizontalHeader()->setStretchLastSection(true);

	// 初始化页面信息
	updatePageInfo();
}

void CLogHisDlg::initModel()
{
	m_pModel = new QStandardItemModel(this);
	m_pModel->setColumnCount(6);
	QStringList headers;
	headers << QString::fromLocal8Bit("序号")
		<< QString::fromLocal8Bit("级别")
		<< QString::fromLocal8Bit("设备")
		<< QString::fromLocal8Bit("时间")
		<< QString::fromLocal8Bit("模块")
		<< QString::fromLocal8Bit("内容");
	m_pModel->setHorizontalHeaderLabels(headers);

	ui.tableView->setModel(m_pModel);

	// 设置列宽
	ui.tableView->setColumnWidth(0, 50);   // 序号
	ui.tableView->setColumnWidth(1, 100);   // 级别
	ui.tableView->setColumnWidth(2, 150);  // 设备
	ui.tableView->setColumnWidth(3, 140);  // 时间
	ui.tableView->setColumnWidth(4, 100);   // 模块
	// 内容列自动拉伸
}

QVector<QSharedPointer<LogData>> CLogHisDlg::queryLogs(const QString& date, const QString& keyword, const QString& deviceName, const QString& levelDesc)
{
	QVector<QSharedPointer<LogData>> resultLogs;

	// 确定要查询的设备列表
	QVector<QString> queryDevices;
	if (deviceName == "*" || deviceName.isEmpty())
	{
		queryDevices = m_vecDeviceNames; // 查询全部
	}
	else
	{
		queryDevices.append(deviceName); // 查询指定设备
	}

	// 转换级别描述为级别值
	int levelFilter = -1;
	if (levelDesc != "*" && !levelDesc.isEmpty())
	{
		levelFilter = getLevelFromString(levelDesc);
	}

	// 转换日期格式
	QDate queryDate = QDate::fromString(date, "yyyy/MM/dd");
	if (!queryDate.isValid()) 
	{
		queryDate = QDate::currentDate();
	}

	QString dateStr = queryDate.toString("yyyyMMdd");
	QString year = queryDate.toString("yyyy");
	QString month = queryDate.toString("yyyyMM");

	// 为每个设备查询日志
	for (const QString& device : queryDevices) 
	{
		// 构建日志文件路径
		QString appDir = QCoreApplication::applicationDirPath();
		QString logDir = QString("%1/Log/%2/%3/%4/%5/")
			.arg(appDir)
			.arg(m_sModuleName)
			.arg(device)
			.arg(year)
			.arg(month);

		QString fileName = QString("%1%2.log").arg(device).arg(dateStr);
		QString filePath = QDir(logDir).absoluteFilePath(fileName);

		// 如果日志文件不存在，跳过
		if (!QFile::exists(filePath)) 
		{
			continue;
		}

		// 读取日志文件并筛选
		QVector<QSharedPointer<LogData>> deviceLogs = readLogFileFromEnd(filePath, m_sModuleName, device, keyword, levelFilter);

		// 添加到结果中
		resultLogs.append(deviceLogs);
	}

	// 按时间排序（最新的在前面）
	std::sort(resultLogs.begin(), resultLogs.end(),
		[](const QSharedPointer<LogData>& a, const QSharedPointer<LogData>& b)
	{
		QDateTime timeA = QDateTime::fromString(a->sTime, "yyyy-MM-dd hh:mm:ss");
		QDateTime timeB = QDateTime::fromString(b->sTime, "yyyy-MM-dd hh:mm:ss");
		return timeA > timeB; // 降序排列
	});

	return resultLogs;
}

QSharedPointer<LogData> CLogHisDlg::parseLogLine(const QString& line, const QString& moduleName, const QString& deviceName) const
{
	if (line.isEmpty()) 
	{
		return nullptr;
	}

	// 使用正则表达式匹配中括号内容
	QRegExp regex("\\[([^\\]]*)\\]");
	int pos = 0;
	QStringList parts;

	while ((pos = regex.indexIn(line, pos)) != -1)
	{
		QString captured = regex.cap(1).trimmed();
		if (!captured.isEmpty()) 
		{
			parts.append(captured);
		}
		pos += regex.matchedLength();

		if (parts.size() >= 10) 
		{
			break;
		}
	}

	if (parts.size() < 4) 
	{
		return nullptr;
	}

	QString levelStr = parts[0];
	QString timestamp = parts[1];
	QString funcName = parts[2];
	QString logContent = parts[3];

	// 根据级别字符串获取级别枚举值
	int level = getLevelFromString(levelStr);

	// 创建日志数据对象
	return QSharedPointer<LogData>::create(level, levelStr, timestamp, moduleName, deviceName, funcName, logContent);
}

void CLogHisDlg::showCurrentPage()
{
	clearTable();

	if (m_allLogs.isEmpty()) 
	{
		return;
	}

	// 计算当前页的数据范围
	int startIndex = (m_currentPage - 1) * m_pageSize;
	int endIndex = qMin(startIndex + m_pageSize, m_allLogs.size());

	// 添加当前页的数据到表格
	for (int i = startIndex; i < endIndex; ++i) 
	{
		const auto& logData = m_allLogs[i];

		// 获取日志等级配置
		CLogMng& logMng = CLogMng::instance();
		SLogLevelConfig levelConfig = logMng.getLogLevelConfig(logData->nLevel);

		// 根据级别设置颜色
		QBrush fontColor(levelConfig.textColor);
		QBrush backColor(levelConfig.backColor);

		QList<QStandardItem*> items;

		// 序号
		QStandardItem* itemNo = new QStandardItem(QString::number(++m_nNo));
		itemNo->setForeground(fontColor);
		itemNo->setBackground(backColor);
		itemNo->setTextAlignment(Qt::AlignCenter);
		items.append(itemNo);

		// 级别
		QStandardItem* itemLevel = new QStandardItem(logData->sLevel);
		if (!levelConfig.iconPath.isEmpty()) 
		{
			QIcon icon(levelConfig.iconPath);
			if (!icon.isNull()) 
			{
				itemLevel->setIcon(icon);
			}
		}
		itemLevel->setForeground(fontColor);
		itemLevel->setBackground(backColor);
		itemLevel->setTextAlignment(Qt::AlignCenter);
		items.append(itemLevel);

		// 设备
		QStandardItem* itemDevice = new QStandardItem(logData->sDeviceName);
		itemDevice->setForeground(fontColor);
		itemDevice->setBackground(backColor);
		itemDevice->setTextAlignment(Qt::AlignCenter);
		items.append(itemDevice);

		// 时间
		QStandardItem* itemTime = new QStandardItem(logData->sTime);
		itemTime->setForeground(fontColor);
		itemTime->setBackground(backColor);
		itemTime->setTextAlignment(Qt::AlignCenter);
		items.append(itemTime);

		// 模块
		QStandardItem* itemModule = new QStandardItem(logData->sFuncName);
		itemModule->setForeground(fontColor);
		itemModule->setBackground(backColor);
		itemModule->setTextAlignment(Qt::AlignCenter);
		items.append(itemModule);

		// 内容
		QStandardItem* itemContent = new QStandardItem(logData->sLogContent);
		itemContent->setForeground(fontColor);
		itemContent->setBackground(backColor);
		itemContent->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
		items.append(itemContent);

		m_pModel->appendRow(items);
	}

	// 滚动到顶部
	ui.tableView->scrollToTop();
}

void CLogHisDlg::updatePageInfo()
{
	// 更新按钮状态
	ui.pushButtonPre->setEnabled(m_currentPage > 1);
	ui.pushButtonNext->setEnabled(m_currentPage < m_totalPages);

	// 更新页面信息显示
	if (m_allLogs.isEmpty()) 
	{
		ui.labelPageInfo->setText(QString::fromLocal8Bit("第 0/0 页"));
	}
	else 
	{
		ui.labelPageInfo->setText(QString::fromLocal8Bit("第 %1/%2 页 (共 %3 条)")
			.arg(m_currentPage)
			.arg(m_totalPages)
			.arg(m_allLogs.size()));
	}
}

void CLogHisDlg::clearTable()
{
	m_pModel->removeRows(0, m_pModel->rowCount());
	m_nNo = 0;
}

void CLogHisDlg::slotPushQuery()
{
	QString sTime = ui.dateEdit->date().toString("yyyy/MM/dd");
	QString sKey = ui.lineEditKey->text();
	QString sDevName = ui.comboBoxDevice->currentText();
	QString sLevel = ui.comboBoxLevel->currentText();
	// 使用定时器避免界面卡顿
	QTimer::singleShot(50, [this, sTime, sKey, sDevName, sLevel]() 
	{
		try
		{
			// 查询日志
			m_allLogs = queryLogs(sTime, sKey, sDevName, sLevel);

			if (m_allLogs.isEmpty())
			{
				clearTable();
				m_currentPage = 1;
				m_totalPages = 1;
			}
			else 
			{
				// 计算总页数
				m_totalPages = (m_allLogs.size() + m_pageSize - 1) / m_pageSize;
				m_currentPage = 1;
				// 显示第一页
				showCurrentPage();
			}
			updatePageInfo();
		}
		catch (const std::exception& e)
		{
			qCritical() << "Query logs failed:" << e.what();
		}
	});
}

void CLogHisDlg::slotPushPrePage()
{
	if (m_currentPage <= 1)
	{
		return;
	}

	m_currentPage--;
	showCurrentPage();
	updatePageInfo();
}

void CLogHisDlg::slotPushNextPage()
{
	if (m_currentPage >= m_totalPages)
	{
		return;
	}

	m_currentPage++;
	showCurrentPage();
	updatePageInfo();
}

void CLogHisDlg::slotPushAddDay()
{
	QDate currDay = ui.dateEdit->date();
	ui.dateEdit->setDate(currDay.addDays(1));
	slotPushQuery();
}

void CLogHisDlg::slotPushPreDay()
{
	QDate currDay = ui.dateEdit->date();
	ui.dateEdit->setDate(currDay.addDays(-1));
	slotPushQuery();
}

void CLogHisDlg::slotDoubleClick()
{
	int nRow = ui.tableView->currentIndex().row();
	CLogDetails oper;
	QString sLevel = m_pModel->item(nRow, 1)->text();
	QString sDeviceName = m_pModel->item(nRow, 2)->text();
	QString sTime = m_pModel->item(nRow, 3)->text();
	QString sFuncName = m_pModel->item(nRow, 4)->text();
	QString sLog = m_pModel->item(nRow, 5)->text();
	oper.setDate(sDeviceName, sTime, sFuncName, sLevel, sLog);
	oper.exec();
}

QVector<QSharedPointer<LogData>> CLogHisDlg::readLogFileFromEnd(const QString& filePath, const QString& moduleName, const QString& deviceName, const QString& keyword, int levelFilter) const
{
	QVector<QSharedPointer<LogData>> filteredLogs;
	filteredLogs.reserve(1000);

	QFile file(filePath);
	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		return filteredLogs;
	}

	// 获取文件大小
	qint64 fileSize = file.size();
	if (fileSize > 10 * 1024 * 1024) // 如果文件大于10MB
	{
		// 从文件末尾开始读取（获取最新日志）
		return readLargeLogFile(file, filePath, moduleName, deviceName, keyword, levelFilter);
	}
	else
	{
		// 小文件正常读取
		return readSmallLogFile(file, filePath, moduleName, deviceName, keyword, levelFilter);
	}
}

QVector<QSharedPointer<LogData>> CLogHisDlg::readSmallLogFile(QFile& file, const QString& filePath, const QString& moduleName,
	const QString& deviceName, const QString& keyword, int levelFilter) const
{
	QVector<QSharedPointer<LogData>> filteredLogs;
	filteredLogs.reserve(1000);

	QTextStream stream(&file);
	stream.setCodec("UTF-8");

	QString line;
	int lineCount = 0;
	const int MAX_LINES = 100000;

	while (stream.readLineInto(&line) && lineCount < MAX_LINES)
	{
		lineCount++;
		line = line.trimmed();
		if (line.isEmpty())
			continue;

		// 快速关键词检查
		if (!keyword.isEmpty() && !line.contains(keyword, Qt::CaseInsensitive))
			continue;

		QSharedPointer<LogData> logData = parseLogLine(line, moduleName, deviceName);
		if (!logData)
			continue;

		if (levelFilter >= 0 && logData->nLevel != levelFilter)
			continue;

		filteredLogs.append(logData);

		if (filteredLogs.size() >= 100000)
			break;
	}

	file.close();
	return filteredLogs;
}

QVector<QSharedPointer<LogData>> CLogHisDlg::readLargeLogFile(QFile& file, const QString& filePath, const QString& moduleName,
	const QString& deviceName, const QString& keyword, int levelFilter) const
{
	QVector<QSharedPointer<LogData>> filteredLogs;
	filteredLogs.reserve(1000);

	const qint64 CHUNK_SIZE = 64 * 1024; // 64KB chunks
	const int MAX_LOGS = 100000; // 最多读取100000条日志

	qint64 fileSize = file.size();
	qint64 pos = qMax(fileSize - CHUNK_SIZE, qint64(0));

	QVector<QString> recentLines;
	int totalLogsCollected = 0;

	// 从文件末尾向前读取
	while (pos >= 0 && totalLogsCollected < MAX_LOGS)
	{
		file.seek(pos);
		QTextStream stream(&file);
		stream.setCodec("UTF-8");

		// 读取一个chunk
		QString chunk = stream.read(CHUNK_SIZE);
		QStringList lines = chunk.split('\n');

		// 反转顺序，因为是从后往前读
		for (auto it = lines.rbegin(); it != lines.rend(); ++it)
		{
			QString line = it->trimmed();
			if (!line.isEmpty())
			{
				recentLines.prepend(line);
				totalLogsCollected++;
			}

			if (totalLogsCollected >= MAX_LOGS)
				break;
		}

		if (pos == 0 || totalLogsCollected >= MAX_LOGS)
			break;

		pos = qMax(pos - CHUNK_SIZE, qint64(0));
	}

	file.close();

	// 处理收集到的日志行
	for (const QString& line : recentLines)
	{
		// 快速关键词检查
		if (!keyword.isEmpty() && !line.contains(keyword, Qt::CaseInsensitive))
		{
			continue;
		}

		QSharedPointer<LogData> logData = parseLogLine(line, moduleName, deviceName);
		if (!logData)
		{
			continue;
		}

		if (levelFilter >= 0 && logData->nLevel != levelFilter)
		{
			continue;
		}

		filteredLogs.append(logData);

		if (filteredLogs.size() >= 100000) // 限制结果数量
		{
			break;
		}
	}

	return filteredLogs;
}
